home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / SCIENTIF / H381.ZIP / GSRC208A.ZIP / EDRATEQ.C < prev    next >
C/C++ Source or Header  |  1993-07-13  |  20KB  |  738 lines

  1. #include "copyleft.h"
  2.  
  3. /*
  4.     GEPASI - a simulator of metabolic pathways and other dynamical systems
  5.     Copyright (C) 1989, 1992  Pedro Mendes
  6. */
  7.  
  8. /*************************************/
  9. /*                                   */
  10. /*          GWTOP - Topology         */
  11. /*        MS-WINDOWS front end       */
  12. /*                                   */
  13. /*       User-defined kinetics       */
  14. /*                                   */
  15. /*           QuickC/WIN 1.0          */
  16. /*                                   */
  17. /*   (include here compilers that    */
  18. /*   compiled GWSIM successfully)    */
  19. /*                                   */
  20. /*************************************/
  21.  
  22.  
  23. #include <windows.h>
  24. #include <stdio.h>
  25. #include <string.h>
  26. #include <stdlib.h>
  27. #include "defines.h"                    /* symbols also used in .DLG files        */
  28. #include "globals.h"                    /* gepasi's own symbols                    */
  29. #include "gwtop.h"                        /* macros, function prototypes, etc.    */
  30. #include "gep1.h"                        /* gepasi's variables                    */
  31. #include "topgvar.h"                    /* global variables                        */
  32. #include "strtbl.h"                        /* symbols for the string table            */
  33.  
  34. #define YY_NULL 0
  35. int rightprec( unsigned char nu );
  36. int leftprec( unsigned char nu );
  37. unsigned char parse_prim( void );
  38. unsigned char parse_expr( int priority );
  39. int lexic( char *line );
  40. int point_error( char *b );
  41. int yylex( void );
  42. void yyreset( void );
  43. void AddKLst( HWND hControl, int idx );
  44.  
  45. #pragma alloc_text( CODE1, rightprec, leftprec, parse_expr, parse_prim, lexic, point_error, EdRateq, EdRDet, EdNSub, AddKLst, EdUdkt)
  46.  
  47. int errfl, errnode;
  48. extern char *yyin;
  49.  
  50. int rightprec( unsigned char nu )
  51. {
  52.  int n;
  53.  
  54.  n = (int) nu;
  55.  switch( tr.node[n].item )
  56.  {
  57.   case 'N':
  58.   case 'I': return 6;
  59.   case 'F': return 4;
  60.  }
  61.  switch( tr.node[n].val )
  62.  {
  63.   case '+':
  64.   case '-': return 2;
  65.   case '*':
  66.   case '/': return 4;
  67.   case ')': return 6;
  68.   case '^': return 4;
  69.   case '(':
  70.   case '%': return 0;
  71.  }
  72. }
  73.  
  74. int leftprec( unsigned char nu )
  75. {
  76.  int n;
  77.  
  78.  n = (int) nu;
  79.  switch( tr.node[n].item )
  80.  {
  81.   case 'N':
  82.   case 'I':
  83.   case 'F': return 5;
  84.  }
  85.  switch( tr.node[n].val )
  86.  {
  87.   case '+':
  88.   case '-': return 1;
  89.   case '*':
  90.   case '/': return 3;
  91.   case '(': return 6;
  92.   case '^': return 5;
  93.   case ')':
  94.   case '%': return 0;
  95.  }
  96. }
  97.  
  98. unsigned char parse_expr( int priority )
  99. {
  100.  unsigned char lhs, rhs, op;
  101.  
  102.  lhs = parse_prim();
  103.  if( lhs == (unsigned char) 255 ) return (unsigned char) 255;
  104.  
  105.  for( ; tr.node[(int)lex].item=='O' && priority < leftprec( lex ); )
  106.  {
  107.   op = lex;
  108.   rhs = (unsigned char) 255;
  109.   ++lex;
  110.   rhs = parse_expr( rightprec( op ) );
  111.   if( rhs == (unsigned char) 255 )
  112.   {
  113.    if( !errfl )
  114.    {
  115.     sprintf( errstr, "ERROR - unexpected operator" );
  116.     errnode = (int) op;
  117.    }
  118.    errfl++;
  119.   }
  120.   else
  121.   {
  122.    tr.node[(int)op].left = lhs;
  123.    tr.node[(int)op].right = rhs;
  124.    lhs = op ;
  125.   }
  126.  }
  127.  
  128.  return lhs;
  129. }
  130.  
  131. unsigned char parse_prim( void )
  132. {
  133.  unsigned char nodep, op, primary;
  134.  char t;
  135.  
  136.  nodep = (unsigned char) 255;
  137.  
  138.  if( (tr.node[(int)lex].item=='N') || (tr.node[(int)lex].item=='I') ) t='K';
  139.  else t = tr.node[(int)lex].val;
  140.  
  141.  switch( t )
  142.  {
  143.   case 'K': tr.node[(int)lex].left = tr.node[(int)lex].right = (unsigned char) 255;
  144.             nodep = lex;
  145.             ++lex;
  146.             return nodep;
  147.  
  148.   case '(': ++lex;
  149.             nodep = parse_expr( 0 );
  150.             if( (tr.node[(int)lex].item=='O') && (tr.node[(int)lex].val==')') )
  151.             {
  152.              ++lex;
  153.              return nodep;
  154.             }
  155.             else
  156.             {
  157.              if( !errfl )
  158.              {
  159.               sprintf( errstr, "ERROR - right bracket missing" );
  160.               errnode = (int) lex;
  161.              }
  162.              errfl++;
  163.             }
  164.  
  165.   case '+':
  166.   case '-':
  167.   case 'L':
  168.   case 'l':
  169.   case 'e':
  170.   case 'S':
  171.   case 'C': op = lex; primary = (unsigned char) 255;
  172.             ++lex;
  173.             primary = parse_prim();
  174.             if( primary==(unsigned char)255 )
  175.             {
  176.              if( !errfl )
  177.              {
  178.               sprintf( errstr, "ERROR - missing operator" );
  179.               errnode = (int) op;
  180.              }
  181.              errfl++;
  182.             }
  183.             else
  184.             {
  185.              nodep = op;
  186.              tr.node[(int)op].item = 'F';
  187.              tr.node[(int)op].left = primary;
  188.              tr.node[(int)op].right = (unsigned char) 255;
  189.              return nodep;
  190.             }
  191.   default:  return (unsigned char) 255;
  192.  }
  193.  
  194.  if( (tr.node[(int)lex].item=='O') &&
  195.      (tr.node[(int)lex].val=='(')
  196.    )
  197.  {
  198.   ++lex;
  199.   if( (tr.node[(int)lex].item=='O') &&
  200.       (tr.node[(int)lex].val==')')
  201.     )
  202.   {
  203.    tr.node[(int)lex].left = nodep;
  204.    tr.node[(int)lex].right = (unsigned char) 255;
  205.    return lex;
  206.   }
  207.   else parse_expr( 0 );
  208.  }
  209. }
  210.  
  211. int lexic( char *line )
  212. {
  213.  int i;
  214.  
  215.  for( i=1; i<255; i++ )
  216.   tr.node[i].left = tr.node[i].right = 0;
  217.  
  218.  tr.node[0].item='%';
  219.  tr.node[0].val='%';
  220.  tr.node[0].right=(unsigned char) 255;
  221.  
  222.  yyreset();
  223.  tr.nnode = 1;
  224.  tr.nid = 0;
  225.  tr.nnum = 0;
  226.  yyin = line;
  227.  lex = 1;
  228.  
  229.  for( errfl=0; ; )
  230.  {
  231.   if( tr.nnode==254 )
  232.   {
  233.    if( !errfl )
  234.     sprintf( errstr, "ERROR - expression too long" );
  235.    errfl++;
  236.    break;
  237.   }
  238.   if( yylex() == YY_NULL ) break;
  239.  }
  240.  
  241.  if( !errfl ) tr.node[0].left = parse_expr( 0 );
  242.  
  243.  if( (tr.node[tr.node[0].left].item == 'O') &&
  244.      (tr.node[tr.node[0].left].val == '(' )
  245.    )
  246.  {
  247.   sprintf( errstr, "ERROR - missing operand" );
  248.   errnode = tr.node[0].left - 1;
  249.   errfl++;
  250.  }
  251.  
  252.  for( i=1; (i<tr.nnode)&&(!errfl); i++ )
  253.  {
  254.   switch( tr.node[i].item )
  255.   {
  256.    case 'O': if( ( tr.node[i].left  == (unsigned char) 255 ) ||
  257.                  ( tr.node[i].right == (unsigned char) 255 ) ||
  258.                  ( tr.node[i].left == (unsigned char) 0 )    ||
  259.                  ( tr.node[i].right == (unsigned char) 0 )
  260.                )
  261.               if( (tr.node[i].val!='(') && (tr.node[i].val!=')') )
  262.               {
  263.                if( !errfl )
  264.                {
  265.                 sprintf( errstr, "ERROR - incorrect number of operands" );
  266.                 errnode = i;
  267.                }
  268.                errfl++;
  269.               }
  270.              if( !errfl )
  271.              {
  272.               if( (tr.node[tr.node[i].left].item == 'O') &&
  273.                   (tr.node[tr.node[i].left].val == '(')
  274.                 )
  275.               {
  276.                sprintf( errstr, "ERROR - missing operand" );
  277.                errnode = tr.node[i].left - 1;
  278.                errfl++;
  279.               }
  280.               if( (tr.node[tr.node[i].right].item == 'O') &&
  281.                   (tr.node[tr.node[i].right].val == ')')
  282.                 )
  283.               {
  284.                sprintf( errstr, "ERROR - missing operand" );
  285.                errnode = tr.node[i].right - 1;
  286.                errfl++;
  287.               }
  288.              }
  289.              break;
  290.  
  291.    case 'I': if( ( tr.node[i].left == (unsigned char) 0 )  ||
  292.                  ( tr.node[i].right == (unsigned char) 0 )
  293.                )
  294.              {
  295.               if( !errfl )
  296.               {
  297.                sprintf( errstr, "ERROR - unexpected identifier" );
  298.                errnode = i-1;
  299.               }
  300.               errfl++;
  301.              }
  302.              break;
  303.    case 'N': if( ( tr.node[i].left == (unsigned char) 0 )    ||
  304.                  ( tr.node[i].right == (unsigned char) 0 )       )
  305.              {
  306.               if( !errfl )
  307.               {
  308.                sprintf( errstr, "ERROR - unexpected constant" );
  309.                errnode = i-1;
  310.               }
  311.               errfl++;
  312.              }
  313.              break;
  314.   }
  315.  }
  316.  
  317.  return errfl;
  318. }
  319.  
  320. int point_error( char *b )
  321. {
  322.  int pt, i;
  323.  char astr[64];
  324.  
  325.  pt = 0;
  326.  strcpy( b, "" );
  327.  for( i=1; i<tr.nnode; i++ )
  328.  {
  329.   switch( tr.node[i].item )
  330.   {
  331.    case 'N': sprintf( astr, "%g", tr.constant[(int)tr.node[i].val] ); break;
  332.    case 'I': sprintf( astr, "%s", tr.id[(int)tr.node[i].val] ); break;
  333.    case 'O': sprintf( astr, "%c", tr.node[i].val ); break;
  334.    case 'F': switch( tr.node[i].val )
  335.              {
  336.               case '+': sprintf( astr, "+" ); break;
  337.               case '-': sprintf( astr, "-" ); break;
  338.               case 'L': sprintf( astr, "log" ); break;
  339.               case 'l': sprintf( astr, "ln" ); break;
  340.               case 'e': sprintf( astr, "exp" ); break;
  341.               case 'S': sprintf( astr, "sin" ); break;
  342.               case 'C': sprintf( astr, "cos" ); break;
  343.              }
  344.   }
  345.   strcat( b, astr );
  346.   if( errfl && (errnode==i) ) pt = strlen( b );
  347.  }
  348.  
  349.  if( pt==0 ) pt = strlen( b );
  350.  return pt;
  351. }
  352.  
  353.  
  354. BOOL FAR PASCAL EdRateq( HWND hDlg, WORD message, WORD wParam, LONG lParam )
  355. {
  356.  static    HWND    hEdit;
  357.  char buff[2048];
  358.  int p;
  359.  
  360.  switch( message )
  361.  {
  362.   case WM_INITDIALOG:
  363.    /* get the handle to the edit control                            */
  364.    hEdit = GetDlgItem( hDlg, IDE_M0 );
  365.  
  366.    /* Limit the length of the equation to 2047 characters            */
  367.    SendMessage( hEdit, EM_LIMITTEXT, (WORD) 2047, 0 );
  368.  
  369.    /* if eqefl is set this is an edit of an existing kinetic type    */
  370.    if( eqefl )
  371.    {
  372.     errfl = 0;                 /* no errors yet    */
  373.     p = point_error( buff );
  374.     SendMessage( hEdit, WM_SETTEXT, 0, (DWORD) (LPSTR) buff );
  375.     SendMessage( hEdit, EM_SETSEL, 0, MAKELONG( p, p ) );
  376.     yyreset();
  377.    }
  378.  
  379.    /* set the focus on the edit control                                */
  380.    SetFocus( hEdit );
  381.  
  382.    return TRUE;
  383.  
  384.   case WM_COMMAND:
  385.    switch( wParam )
  386.    {
  387.     case IDC_HELP:                        /* Help for this Dialog Box             */
  388.      WinHelp( hDlg, (LPSTR) szHelpFile, HELP_KEY, (DWORD) (LPSTR) "Rate equation editor" );
  389.      SetFocus( hEdit );
  390.      return TRUE;
  391.  
  392.     case IDOK:
  393.      SendMessage( hEdit, WM_GETTEXT, (WORD) sizeof( buff ), (DWORD) (LPSTR) buff );
  394.      if( lexic( buff ) )
  395.      {
  396.       MessageBeep( MB_OK );
  397.       MessageBox( hDlg, errstr, (LPSTR) "Rate Equation Editor", MB_ICONINFORMATION );
  398.       p = point_error( buff );
  399.       SendMessage( hEdit, WM_SETTEXT, 0, (DWORD) (LPSTR) buff );
  400.       SendMessage( hEdit, EM_SETSEL, 0, MAKELONG( p, p ) );
  401.       yyreset();
  402.      }
  403.      else
  404.       EndDialog( hDlg, IDOK );
  405.      return TRUE;
  406.  
  407.     case IDCANCEL:
  408.      /* close the dialog box and return            */
  409.      EndDialog( hDlg, IDCANCEL );
  410.      return TRUE;
  411.    }
  412.  
  413.   default: return FALSE;
  414.  }
  415. }
  416.  
  417. BOOL FAR PASCAL EdRDet( HWND hDlg, WORD message, WORD wParam, LONG lParam )
  418. {
  419.  static    HWND    hIdLst, hEdit;
  420.  static int     id_sel;
  421.  int i;
  422.  
  423.  switch( message )
  424.  {
  425.   case WM_INITDIALOG:
  426.    /* get the handles to the controls                                */
  427.    hIdLst = GetDlgItem( hDlg, IDC_PARAMLST );
  428.    hEdit  = GetDlgItem( hDlg, IDE_M0 );
  429.  
  430.    SendMessage( hEdit, WM_SETTEXT, 0, (DWORD) (LPSTR) tr.descr );
  431.    if( tr.nid>0 )
  432.    {
  433.     /* insert the identifiers in the list box                        */
  434.     for( i=0; i<tr.nid; i++ )
  435.      SendMessage( hIdLst, LB_INSERTSTRING, i, (DWORD) (LPSTR) &tr.id[i][0] );
  436.  
  437.     /* select the first id on the list                                */
  438.     SendMessage( hIdLst, LB_SETCURSEL, 0, 0 );
  439.     id_sel = 0;
  440.     SendDlgItemMessage( hDlg, IDRB_0E+(int)tr.id[id_sel][9], BM_SETCHECK, (WORD) 1, 0 );
  441.     SendDlgItemMessage( hDlg, IDRB_9I, BM_SETCHECK, (WORD) tr.revers, 0 );
  442.  
  443.    /* set the focus on the list box                                    */
  444.    SetFocus( hIdLst );
  445.    }
  446.    else
  447.    {
  448.     EnableWindow( hIdLst, FALSE );
  449.     for( i=IDRB_0E; i<=IDRB_1I; i++ )
  450.      EnableWindow( GetDlgItem( hDlg, i ), FALSE );
  451.    }
  452.  
  453.    /* set the reversibility status                                    */
  454.    SendMessage( GetDlgItem( hDlg, IDRB_9I ), BM_GETCHECK, (WORD) tr.revers, 0 );
  455.  
  456.    /* Limit the length of the title to 64 characters                */
  457.    SendMessage( hEdit, EM_LIMITTEXT, (WORD) 64, 0 );
  458.  
  459.    return TRUE;
  460.  
  461.   case WM_COMMAND:
  462.    switch( wParam )
  463.    {
  464.     case IDC_PARAMLST:
  465.      if( HIWORD( lParam ) == LBN_SELCHANGE )
  466.      {
  467.       id_sel = (int) SendMessage( hIdLst, LB_GETCURSEL, 0, 0 );
  468.       for(i=IDRB_0E; i<=IDRB_1I; i++ )
  469.        SendDlgItemMessage( hDlg, i, BM_SETCHECK, 0, 0 );
  470.       SendDlgItemMessage( hDlg, IDRB_0E+(int)tr.id[id_sel][9], BM_SETCHECK, (WORD) 1, 0 );
  471.       return TRUE;
  472.      }
  473.      else return FALSE;
  474.  
  475.     case IDRB_0E:
  476.      tr.id[id_sel][9] = (char) 0;
  477.      return TRUE;
  478.  
  479.     case IDRB_0I:
  480.      tr.id[id_sel][9] = (char) 1;
  481.      return TRUE;
  482.  
  483.     case IDRB_1E:
  484.      tr.id[id_sel][9] = (char) 2;
  485.      return TRUE;
  486.  
  487.     case IDRB_1I:
  488.      tr.id[id_sel][9] = (char) 3;
  489.      return TRUE;
  490.  
  491.     case IDRB_9I:
  492.      if( SendMessage( GetDlgItem( hDlg, IDRB_9I ), BM_GETCHECK, 0, 0 ) )
  493.       tr.revers = 1;
  494.      else
  495.       tr.revers = 0;
  496.      return TRUE;
  497.  
  498.     case IDC_HELP:                        /* Help for this Dialog Box             */
  499.         WinHelp( hDlg, (LPSTR) szHelpFile, HELP_KEY, (DWORD) (LPSTR) "Rate equation details" );
  500.      SetFocus( hEdit );
  501.      return TRUE;
  502.  
  503.     case IDOK:
  504.      SendMessage( hEdit, WM_GETTEXT, (WORD) sizeof( tr.descr ), (DWORD) (LPSTR) &tr.descr[0] );
  505.      if( strlen( tr.descr ) == 0 )
  506.      {
  507.       LoadString( hInst, IDS_ERR_NO_NAME, szString, sizeof(szString) );
  508.       MessageBeep( MB_OK );
  509.       MessageBox(hDlg, szString, NULL, MB_ICONINFORMATION);
  510.       return TRUE;
  511.      }
  512.      EndDialog( hDlg, IDOK );
  513.      return TRUE;
  514.  
  515.     case IDCANCEL:
  516.      /* close the dialog box and return            */
  517.      EndDialog( hDlg, IDCANCEL );
  518.      return TRUE;
  519.    }
  520.  
  521.   default: return FALSE;
  522.  }
  523. }
  524.  
  525. BOOL FAR PASCAL EdNSub( HWND hDlg, WORD message, WORD wParam, LONG lParam )
  526. {
  527.  static    HWND    hEdit, hEdit2;
  528.  char auxstr[33];
  529.  static int s, p;
  530.  
  531.  switch( message )
  532.  {
  533.   case WM_INITDIALOG:
  534.    /* get the handles to the edit controls                            */
  535.    hEdit = GetDlgItem( hDlg, IDE_M0 );
  536.    hEdit2 = GetDlgItem( hDlg, IDE_M1 );
  537.    /* Limit the length of the text to 32 characters                    */
  538.    SendMessage( hEdit,  EM_LIMITTEXT, (WORD) 32, 0 );
  539.    SendMessage( hEdit2, EM_LIMITTEXT, (WORD) 32, 0 );
  540.  
  541.    wsprintf( (LPSTR) auxstr, "%d", tr.nsub );
  542.    SendMessage( hEdit,  WM_SETTEXT, 0, (DWORD) (LPSTR) auxstr );
  543.    wsprintf( (LPSTR) auxstr, "%d", tr.npro );
  544.    SendMessage( hEdit2,  WM_SETTEXT, 0, (DWORD) (LPSTR) auxstr );
  545.    return TRUE;
  546.  
  547.   case WM_COMMAND:
  548.    switch( wParam )
  549.    {
  550.     case IDC_HELP:                        /* Help for this Dialog Box             */
  551.         WinHelp( hDlg, (LPSTR) szHelpFile, HELP_KEY, (DWORD) (LPSTR) "Number of substrates" );
  552.      SetFocus( hEdit );
  553.      return TRUE;
  554.  
  555.     case IDOK:
  556.      SendMessage( hEdit2, WM_GETTEXT, (WORD) sizeof( auxstr ), (DWORD) (LPSTR) auxstr );
  557.      tr.npro = atoi( auxstr );
  558.      SendMessage( hEdit, WM_GETTEXT, (WORD) sizeof( auxstr ), (DWORD) (LPSTR) auxstr );
  559.      tr.nsub = atoi( auxstr );
  560.      if( tr.nsub<0 )
  561.      {
  562.       LoadString( hInst, IDS_ERR_NEG, szString, sizeof(szString) );
  563.       MessageBeep( MB_OK );
  564.       MessageBox(hDlg, szString, NULL, MB_ICONINFORMATION);
  565.       SetFocus( hEdit );
  566.       return TRUE;
  567.      }
  568.      if( (tr.revers) && (tr.nsub==0) )
  569.      {
  570.       LoadString( hInst, IDS_ERR_NO_SUBS, szString, sizeof(szString) );
  571.       MessageBeep( MB_OK );
  572.       MessageBox(hDlg, szString, NULL, MB_ICONINFORMATION);
  573.       SetFocus( hEdit );
  574.       return TRUE;
  575.      }
  576.      if( tr.npro<0 )
  577.      {
  578.       LoadString( hInst, IDS_ERR_NEG, szString, sizeof(szString) );
  579.       MessageBeep( MB_OK );
  580.       MessageBox(hDlg, szString, NULL, MB_ICONINFORMATION);
  581.       SetFocus( hEdit2 );
  582.       return TRUE;
  583.      }
  584.      if( (tr.revers) && (tr.npro==0) )
  585.      {
  586.       LoadString( hInst, IDS_ERR_NO_PRODS, szString, sizeof(szString) );
  587.       MessageBeep( MB_OK );
  588.       MessageBox(hDlg, szString, NULL, MB_ICONINFORMATION);
  589.       SetFocus( hEdit2 );
  590.       return TRUE;
  591.      }
  592.      EndDialog( hDlg, IDOK );
  593.      return TRUE;
  594.  
  595.     case IDCANCEL:
  596.      /* close the dialog box and return            */
  597.      EndDialog( hDlg, IDCANCEL );
  598.      return TRUE;
  599.    }
  600.  
  601.   default: return FALSE;
  602.  }
  603. }
  604.  
  605. void AddKLst( HWND hControl, int idx )
  606. {
  607.  int i;
  608.  WORD ElWidth;
  609.  HANDLE hDC;
  610.  
  611.  hDC = GetDC( hControl );
  612.  ElWidth = 5 + LOWORD( GetTextExtent( hDC, tree[idx].descr, _fstrlen(tree[idx].descr) ) );
  613.  SetTextJustification( hDC, 0, 0 );
  614.  ReleaseDC( hControl, hDC );
  615.  if( ElWidth > (WORD) lbWidth )
  616.  {
  617.   lbWidth = ElWidth;
  618.   SendMessage( hControl, LB_SETHORIZONTALEXTENT, lbWidth, 0 );
  619.  }
  620.  if( eqefl )
  621.  {
  622.   SendMessage( hControl, LB_DELETESTRING, idx, 0 );
  623.   SendMessage( hControl, LB_INSERTSTRING, idx, (DWORD) tree[idx].descr );
  624.  }
  625.  else
  626.  {
  627.   SendMessage( hControl, LB_INSERTSTRING, -1, (DWORD) tree[idx].descr );
  628.   SendMessage( hControl, WM_VSCROLL, SB_BOTTOM, 0 );
  629.  }
  630. }
  631.  
  632. BOOL FAR PASCAL EdUdkt(HWND hDlg, WORD Message, WORD wParam, LONG lParam)
  633. {
  634.  static HWND hSelect, hButt, hDel;
  635.  static int eqidx;
  636.  int i,j,nRc;
  637.  FARPROC lpfnProc2;
  638.  
  639.  switch( Message )
  640.  {
  641.   case WM_INITDIALOG:
  642.    /* get handles for controls                        */
  643.    hSelect = GetDlgItem( hDlg, IDC_KINETLST );
  644.    hButt = GetDlgItem( hDlg, IDC_CHANGE );
  645.    hDel = GetDlgItem( hDlg, IDC_DEL );
  646.  
  647.    /* initialize hSelect: add all rate equations    */
  648.    for( i=0, lbWidth=0; i<nudf; i++ )
  649.     AddKLst( hSelect, i );
  650.    if( nudf==0 )
  651.    {
  652.     EnableWindow( hButt, FALSE );
  653.     EnableWindow( hDel, FALSE );
  654.    }
  655.    else SendMessage( hSelect, LB_SETCURSEL, 0, 0 );
  656.    return TRUE;
  657.  
  658.    case WM_USER+1:
  659.     lpfnProc2 = MakeProcInstance((FARPROC) EdRateq, hInst);
  660.     nRc = DialogBox(hInst, (LPSTR)"EDRATEQ", hDlg, lpfnProc2);
  661.     FreeProcInstance(lpfnProc2);
  662.     if( nRc == IDOK )
  663.     {
  664.      if( eqefl )
  665.       for( i=0; i<tr.nid; i++ )
  666.        for( j=0; j<tree[eqidx].nid; j++ )
  667.         if( ! lstrcmp( &tr.id[i][0], &tree[eqidx].id[j][0] ) )
  668.          tr.id[i][9] = tree[eqidx].id[j][9];
  669.      lpfnProc2 = MakeProcInstance((FARPROC) EdRDet, hInst);
  670.      nRc = DialogBox(hInst, (LPSTR)"ED_RDET", hDlg, lpfnProc2);
  671.      FreeProcInstance(lpfnProc2);
  672.      if( nRc == IDOK )
  673.      {
  674.       tidy_tree();
  675.       if( (!tr.revers) ||
  676.           ( (tr.revers) && (tr.nsub==0) ) ||
  677.           ( (tr.revers) && (tr.npro==0) )
  678.         )
  679.       {
  680.        lpfnProc2 = MakeProcInstance((FARPROC) EdNSub, hInst);
  681.        nRc = DialogBox(hInst, (LPSTR)"ED_NSUB", hDlg, lpfnProc2);
  682.        FreeProcInstance(lpfnProc2);
  683.        if( nRc != IDOK ) return TRUE;
  684.       }
  685.       new_tree( eqidx );
  686.       new_rateq( eqidx );
  687.       AddKLst( hSelect, eqidx );
  688.      }
  689.     }
  690.     return TRUE;
  691.  
  692.   case WM_COMMAND:
  693.    switch(wParam)
  694.    {
  695.     case IDC_ADD:
  696.      eqefl = 0; eqidx = nudf;
  697.      _fmemset( (void __far*) &tr, 0, sizeof( struct treet ) );
  698.      SendMessage( hDlg, WM_USER+1, 0, 0 );
  699.      return TRUE;
  700.  
  701.     case IDC_CHANGE:
  702.      /* get the index of the element selected                    */
  703.      eqidx = (int) SendMessage( hSelect, LB_GETCURSEL, 0, 0 );
  704.      if( eqidx != LB_ERR )
  705.      {
  706.       /* signal that it is a change, not a new one                */
  707.       eqefl = 1;
  708.       /* copy it to the edit tree structure                        */
  709.       _fmemcpy( (void __far*) &tr, (void __far*) &(tree[eqidx]), sizeof( struct treet ) );
  710.       SendMessage( hDlg, WM_USER+1, 0, 0 );
  711.      }
  712.      return TRUE;
  713.  
  714.     case IDC_KINETLST:
  715.      if( HIWORD( lParam ) == LBN_DBLCLK )
  716.      {
  717.       SendMessage( hDlg, WM_COMMAND, IDC_CHANGE, 0 );
  718.       return TRUE;
  719.      }
  720.      else return FALSE;
  721.  
  722.     case IDC_HELP:            /* Help on this Dialog Box                */
  723.         WinHelp( hDlg, (LPSTR) szHelpFile, HELP_KEY, (DWORD) (LPSTR) "Kinetic types database" );
  724.      return TRUE;
  725.  
  726.     case IDOK:
  727.      EndDialog(hDlg, IDOK);
  728.      return TRUE;
  729.  
  730.    }    /* End of WM_COMMAND                                 */
  731.    return FALSE;
  732.  
  733.   default:
  734.    return FALSE;
  735.  }
  736. } /* End of METABMsgProc                                      */
  737.  
  738.